import re
from django.utils import timezone
from django_redis import get_redis_connection
from rest_framework import serializers
from users_lab.models import User, OAuthQQUser


class UserSerializer(serializers.ModelSerializer):
    '''用户注册序列化器类'''
    password2 = serializers.CharField(label='重复密码', max_length=128, write_only=True)
    allow = serializers.BooleanField(write_only=True, label='是否同意协议')
    sms_code = serializers.IntegerField(label='短信验证码', write_only=True)
    token = serializers.CharField(label='JWT Token', read_only=True)

    class Meta:
        model = User
        fields = ('id', 'password2', 'allow', 'sms_code', 'username', 'token', 'password', 'mobile')
        extra_kwargs = {
            'password': {'write_only': True, 'label': '密码'},
            'mobile': {'write_only': True},
        }

    def validate(self, attrs):
        username = attrs['username']
        password = attrs['password']
        password2 = attrs.pop('password2')
        allow = attrs.pop('allow')
        sms_code = attrs.pop('sms_code')
        mobile = attrs['mobile']

        # 校验(整体)
        if not all([username, password, password2, mobile, allow, sms_code]):
            raise serializers.ValidationError('缺少必传参数')

        # username检验
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
            raise serializers.ValidationError('用户名格式错误')

        # password检验
        if not re.match(r'^[a-zA-Z0-9]{8,20}$', password):
            raise serializers.ValidationError('密码格式有误')

        # password2检验
        if password != password2:
            raise serializers.ValidationError('密码输入不匹配')

        # mobile检验
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            raise serializers.ValidationError('手机号格式错误')

        # allow检验
        if allow != True:
            raise serializers.ValidationError('请勾选协议')

        # 短信验证码检验
        # sms_code检验 (链接redis数据库)
        redis_conn = get_redis_connection('verify_code')
        # 从redis中取值
        sms_code_server = redis_conn.get('sms_%s' % mobile)
        res = int(sms_code_server.decode())
        print(res)
        # 判断该值是否存在
        if not sms_code_server:
            raise serializers.ValidationError('短信验证码过期')
        # 11.把redis中取得值和前端发的值对比
        if sms_code != res:
            raise serializers.ValidationError('短信验证码有误')

        return attrs

    def create(self, validated_data):
        user = super().create(validated_data)
        user.set_password(validated_data['password'])
        user.save()
        # 服务器生成jwt token, 保存当前用户的身份信息
        from rest_framework_jwt.settings import api_settings

        # 组织payload数据的方法
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        # 生成jwt token数据的方法
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        # 组织payload数据
        payload = jwt_payload_handler(user)
        # 生成jwt token
        token = jwt_encode_handler(payload)

        # 给user对象增加属性，保存jwt token的数据
        user.token = token

        return user


class UserAuthSerializer(serializers.ModelSerializer):
    '''用户登录序列化器类'''
    username = serializers.CharField(label='用户名')
    token = serializers.CharField(label='JWT Token', read_only=True)
    class Meta:
        model = User
        fields = ('id', 'username', 'password', 'token', 'mobile')
        extra_kwargs = {
            'password': {'write_only': True},
            'mobile': {'required': False, 'write_only': True}
        }

    def validate(self, attrs):
        # 获取username和password
        username = attrs['username']
        password = attrs['password']

        # 进行用户名和密码校验
        if not re.match(r'^1[3-9]\d{9}$', username):
            try:
                user = User.objects.get(username=username)
            except User.DoesNotExist:
                raise serializers.ValidationError('用户名错误')

        else:
            try:
                user = User.objects.get(mobile=username)
            except User.DoesNotExist:
                raise serializers.ValidationError('用户名错误')
        # 校验密码
        if not user.check_password(password):
            raise serializers.ValidationError('密码错误')
        # 给attrs中添加user属性，保存登录用户
        attrs['user'] = user

        return attrs

    def create(self, validated_data):
        # 获取登录用户user
        user = validated_data['user']

        # 设置最新登录时间
        user.last_login = timezone.now()
        user.save()

        # 服务器生成jwt token, 保存当前用户的身份信息
        from rest_framework_jwt.settings import api_settings

        # 组织payload数据的方法
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        # 生成jwt token数据的方法
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        # 组织payload数据
        payload = jwt_payload_handler(user)
        # 生成jwt token
        token = jwt_encode_handler(payload)

        # 给user对象增加属性，保存jwt token的数据
        user.token = token

        return user


class QQUserSerializer(serializers.ModelSerializer):
    username = serializers.CharField(label='用户名')
    password = serializers.IntegerField(write_only=True)
    sms_code = serializers.IntegerField(write_only=True)
    access_token = serializers.CharField(write_only=True)
    token = serializers.CharField(label='JWT Token', read_only=True)
    class Meta:
        model = OAuthQQUser
        fields = ('token','id', 'username', 'sms_code', 'access_token', 'password')
